Sound Manager 3.2 contains some new routines for determining sound formats and converting between sound formats. This document describes the application programming interface to these new features and the bug fixes.
The information described here is confidential and subject to change. Do not share this information with other parties.
Determining Sound Hardware Settings
New Sound Manager routines: GetSoundOutputInfo() and SetSoundOutputInfo().
Two routines have been added to get and set information about the sound environment: GetSoundOutputInfo() and SetSoundOutputInfo. Both routines use a selector-based interface similar to the SPBGetDeviceInfo/SPBSetDeviceInfo routines found in the Sound Input Manager, and in fact they use the same selectors.
GetSoundOutputInfo() and SetSoundOutputInfo() operate directly on a sound output device, and can be used to retrieve and change information about the hardware settings. These routines should be used instead of attempting to communicate directly with sound output components. Setting the output device parameter to nil causes the default output device to be used. These calls are similar to GetSndInfo() and SetSndInfo() but do not require an opened sound channel.
These new calls are only available with Sound Manager version 3.1 or later. Check for this by calling SndSoundManagerVersion() for the installed version.
For example, to determine the sampling rate of the sound hardware on the default output device, you could use this code:
unsigned long *numFrames, unsigned long *dataOffset)
ParseAIFFHeader returns information describing the audio data in the given AIFF file. The fRefNum parameter specifies the open AIFF file to use. The sndInfo parameter is a SoundComponentData structure that returns the following information about the format of the sound in the AIFF file:
flags - always returns 0
format - the sound format (i.e. 'raw ', 'twos', 'MAC3', etc.)
numChannels - the number of channels (i.e. 1 = mono, 2 = stereo)
sampleRate - the sampling rate (in samples/second)
sampleCount - the number of audio samples in the file
buffer - always returns 0
reserved - always returns 0
The numFrames parameter returns the number of frames of audio data in the file, and the dataOffset parameter returns the byte offset of the first audio sample in the file.
Errors:
siInvalidCompression - compression type not supported
badFileFormat - file does not contain valid AIFF data
unsigned long *numFrames, unsigned long *dataOffset)
ParseSndHeader returns information describing the audio data in the given 'snd ' resource handle. The sndHandle parameter specifies the sound handle to use. The sndInfo parameter is a SoundComponentData structure that returns the following information about the format of the sound in the handle:
flags - always returns 0
format - the sound format (i.e. 'raw ', 'twos', 'MAC3', etc.)
numChannels - the number of channels (i.e. 1 = mono, 2 = stereo)
sampleRate - the sampling rate (in samples/second)
sampleCount - the number of audio samples in the handle
buffer - always returns 0
reserved - always returns 0
The numFrames parameter returns the number of frames of audio data in the handle, and the dataOffset parameter returns the byte offset of the first audio sample in the handle.
Errors:
siInvalidCompression - compression type not supported
badFormat - file does not contain valid 'snd ' data
GetCompressionName returns a string describing the given compression format in a string that can be displayed to the user. The compressionType parameter specifies the compression format, and the name is returned in compressionName. This string can be used in pop-up menus and other user interface elements to allow the user to select a compression format.
Errors:
memFullErr - not enough memory to load name
siInvalidCompression - compression type not supported
resNotFound - compression name not available
Converting Sounds
An architecture has been added to Sound Manager 3.2 to allow you to easily convert between sound formats. Some of the operations that can be performed are compression, decompression, channel conversion, sample rate conversion and sample format conversion.
A conversion session is begun by calling SoundConverterOpen, to which you pass the format of the sound to be converted and the resulting output format. A SoundConverter identifier is returned that must be passed to all further routines in this session. SoundConverterClose is used to close the session.
SoundConverterGetBufferSizes allows you to determine input and output buffer sizes based on a target buffer size. This lets you create buffers to fit the conversion established with SoundConverterOpen.
Converting a sound is a three-step process. First, you call SoundConverterBeginConversion to initiate the conversion and reset the SoundConverter to default settings. Then SoundConverterConvertBuffer is called one or more times to convert sequential buffers of the input data to the output format. Finally, when all input data has been converted, SoundConverterEndConversion flushes out any data left in the converter.
SoundConverterOpen sets up the conversion session and returns a SoundConverter identifier to be passed to all further routines. The inputFormat parameter specifies the format of the sound data to be converted using a SoundComponentData structure. The following fields must be set up to describe the sound correctly:
flags - set to 0
format - the sound format (i.e. 'raw ', 'twos', 'MAC3', etc.)
numChannels - the number of channels (i.e. 1 = mono, 2 = stereo)
sampleRate - the sampling rate (in samples/second)
sampleCount - set to 0
buffer - set to 0
reserved - set to 0
The outputFormat parameter specifies the output format, and must be passed fields similar to inputFormat. Output fields that are different from input fields will cause a conversion. For example, if the input sound format is 'raw ' and the output format is 'MAC3', the data resulting from the conversion will be compressed with MACE 3:1. This allows any combination of compression, decompression, channel conversion, sample size conversion and sampling rate conversion. A SoundConverter identifier is returned to manage the session, which must be passed to all further routines.
This routine cannot be called at interrupt time.
Errors:
memFullErr - not enough memory
siInvalidCompression - compression type not supported
SoundConverterClose terminates the session and frees up all memory and services associated with this session.
This routine cannot be called at interrupt time.
Errors:
none
pascal OSErr SoundConverterGetBufferSizes(SoundConverter sc, unsigned long targetBytes,
unsigned long *inputFrames, unsigned long *inputBytes,
unsigned long *outputBytes)
SoundConverterGetBufferSizes is used to determine the input and output buffer sizes for a given target size. This is so you can make sure your buffers will fit the conversion parameters established with SoundConverterOpen.
The targetBytes parameter is the approximate number of bytes you would like both your input and output buffers to be. The inputFrames and inputBytes parameters return the actual size you should make your input buffer, in frames and bytes respectively. The outputBytes parameter returns the size in bytes for your output buffer.
Note: The returned input and output buffer sizes CAN be larger than your target size settings. This is because they are rounded up depending on the format, but they will be very close to the target settings. Also note that the input and output sizes may be very different, depending on the input and output formats given in SoundConverterOpen. The sizes are calculated assuming you will convert all data in the input buffer to the output buffer.
This routine cannot be called at interrupt time.
Errors:
notEnoughBufferSpace - input bytes target too small
unsigned long *outputFrames, unsigned long *outputBytes)
SoundConverterConvertBuffer converts a buffer of data from the input format to the output format. The inputPtr parameter points to the input data, and inputFrames gives the number of frames in that buffer. The outputPtr parameter specifies where the output data should be placed. The output Frames and outputBytes parameters return the number of frames and bytes placed in the output buffer respectively.
This routine will consume all the data in the input buffer, but, depending on the complexity of the conversion, not all the converted data may be put in the output buffer right away. The SoundConverterEndConversion routine is used to flush out all this remaining data before a conversion session is closed.
If you are using this routine in conjunction with SoundConverterGetBufferSizes, it is very important that you do not pass in a value in inputFrames larger than the frames value returned by SoundConverterGetBufferSizes, or you will overflow your output buffer. The SoundConverterConvertBuffer calls converts ALL the input data!
unsigned long *outputFrames, unsigned long *outputBytes)
SoundConverterEndConversion ends a conversion. Any data remaining in the converters is flushed out and returned here.
This routine can be called at interrupt time.
Errors:
none
Conversion Example
The following is an example of how to use the sound conversion architecture to convert a buffer of silence to IMA 4:1, changing the sampling rate in the process.
New version of InstallMoveHHiPatch that will install on PowerMacs when the old Memory Manager is running. On PowerMacs with our new native PowerPC sound components we use more than 3k of the stack. The MoveHHi() in the new ROMs will only preserve 3k so we have to patch it to preserve more stack space.
Use a nil sound output component reference to specify the default device when calling Get/SetSoundOutputInfo().
Deal with left over samples during compression better by preserving them across calls to PlaySourceBuffer(). This allows sequential calls to a compressor with non-packet multiple buffer sizes to seam together without clicks.
Fixed SetSource() in the format converter so it does not ask the source for 8-bit twos-complement data, which no other sound component supports. This fixes problems when the format converter is installed after the mixer and is asked to output 8-bit twos.
In the sample rate converter the samplesToSkip field now stores the amount to skip into a new buffer. The byteOffset field is updated to this value when a new buffer is received. This fixes a problem playing scales with the freqDuration command when a new buffer is played before the old buffer has reached the end.
The gestaltSoundAttr proc being installed needs to avoid using unknown CPUs or re-cycled machine types.
Sound Input
Multiply bytesPerSample by 8 to get sampleSize for sound header. Fixes bug in SetupSndHeader with arbitrary compression formats.
Hardware
In the 8100 PowerMac series, fixed siHardwareMute support. It was reporting the hardware as muted in some cases when the sound could be heard.
Added speaker and headphone muting into the preferences. This allows for the user to specify the speaker is no muted when using external speakers or headphones, and the next time the machine is started the user's preference is restore. Previously it would default to always muting the speaker if something was inserted into the headphone jack.
Fixed the siHardwareBusy selector in the 8500 series.
Preserve register A0 within DetermineInputSource() when calling GetInitialPreferences().
Interfaces
SndSoundManagerVersion(), SPBVersion(), and MACEVersion() should all return a NumVersion. A recent version of the interfaces were changed to return an unsigned long, but this fails with creating native PowerPC code.
A new version of SoundLib has been released to include all of the new Sound Manager 3.2 API.